typedef enum {
    AS_MOV=1,
    AS_LEA,
    AS_ADD,
    AS_SUB,
    AS_MUL,
    AS_DIV,
    AS_PUSH,
    AS_POP,
    AS_FLD,
    AS_FSTP,
} OpCode;

typedef enum {
    MEM_BYTE=1,
    MEM_WORD,
    MEM_DWORD,
    MEM_QWORD,
} MemSize;

typedef enum {
    R_AL=1,
    R_AX,
    R_EAX,
    R_RAX,
    R_BL,
    R_BX,
    R_EBX,
    R_RBX,
    R_CL,
    R_CX,
    R_ECX,
    R_RCX,
    R_DL,
    R_DX,
    R_EDX,
    R_RDX,
    R_SI,
    R_ESI,
    R_RSI,
    R_DI,
    R_EDI,
    R_RDI,
    R_SP,
    R_ESP,
    R_RSP,
    R_BP,
    R_EBP,
    R_RBP,
    R_R8B,  //8 Bit
    R_R8W,  //16 Bit
    R_R8D,  //32 Bit
    R_R8,   //64 Bit
    R_R9B,
    R_R9W,
    R_R9D,
    R_R9,
    R_XMM,
} Register;

typedef enum {
    OBJ_REG=1,    //寄存器
    OBJ_IMM,    //立即数
    OBJ_MEM,    //内存
    OBJ_STR,    //内存
} codeType;

typedef enum {
    EP_NULL=1,
    EP_NOMemSize,
} GetObjExtendOPT; // 获取对象条件判断选项

typedef struct _obj_{
    codeType type;
    DataType dt;
    // union 
    // {
    //     Register Reg;
    //     Num8 imm;
    // }code;
    struct{
        MemSize size;
        Register name;
    }Reg;

    struct{
        Num8 n;
    }Imm;

    struct{
        MemSize size;
        char *name;
    }Str;
} _OBJ_;

typedef struct _command_{
    OpCode op;
    //MemSize size1;
    _OBJ_ *target;
    //MemSize size2;
    _OBJ_ *source;
} Command;

typedef struct _asm_
{
    void(*mov)(_OBJ_ *target, _OBJ_ *source);
    DataType (*movsx)(_OBJ_ *target, _OBJ_ *source); //符号位扩展
    void(*movzx)(_OBJ_ *target, _OBJ_ *source); //0号位扩展
    void(*lea)(_OBJ_ *target, _OBJ_ *source);
    void(*cvtsd2)(int t, _OBJ_ *target, _OBJ_ *source);
    void(*add)(_OBJ_ *target, _OBJ_ *source);
    void(*sub)(_OBJ_ *target, _OBJ_ *source);
    void(*imul)(_OBJ_ *target, _OBJ_ *source);
    void(*idiv)(_OBJ_ *target, _OBJ_ *source);
    void(*fmov)(DataType t, _OBJ_ *target, _OBJ_ *source); //单精度(4字节) float
    void(*fadd)(DataType t, _OBJ_ *target);
    void(*push)(_OBJ_ *target);
    void(*pop)(_OBJ_ *target);
}Assembly;

//rdi，rsi，rdx，rcx，r8，r9
Assembly *GetCodeGenerator();
_OBJ_ *imm(Num8 n);  //gen.mov(ax(), imm(1));
_OBJ_ *mem(Num8 n, _OBJ_ *target); //mov(mem(4, bp()), ax()) 
_OBJ_ *ax(DataType t);
_OBJ_ *bx(DataType t);

_OBJ_ *StackReg(Num no, DataType t);
_OBJ_ *StackXmm(Num no, DataType t);
//gcc 调用约定寄存器
_OBJ_ *di();
_OBJ_ *si();
_OBJ_ *dx(DataType t);
_OBJ_ *cx();
_OBJ_ *r8();
_OBJ_ *r9();
//push stack

_OBJ_ *sp();
_OBJ_ *xmm();
_OBJ_ *memrel(Num4 no);
_OBJ_ *bp(DataType t);
_OBJ_ *st(DataType t);
_OBJ_ *AutoReg(DataType t);
_OBJ_ *Floating(DataType t);